#include "wxapi.h"

#include <QDir>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QTimer>
#include <QUrlQuery>
#include <QUuid>


wxapi::wxapi(QObject *parent) : QObject(parent)
{
    manager = new QNetworkAccessManager(this);
    get_audio_token_url = QString(get_token_module).arg(grant_type).arg(audio_client_id).arg(audio_client_secret);
    QByteArray body;
    body.clear();
    baidu_networkRequestInterface(get_audio_token_url, body);
    connect(this, &wxapi::send_text_to_doubao_sig, this, &wxapi::post_content_to_doubao);
    connect(this, &wxapi::text_convert_audio_sig, this, &wxapi::post_text_to_baidu_mix1);
    connect(this, &wxapi::mix_task_query_sig, this, &wxapi::post_text_to_baidu_mix2);
    connect(this, &wxapi::download_audio_sig, this, &wxapi::download_audio_from_url);
    //connect(this, &wxapi::playAudioSig, this,  &wxapi::playAudio);

    audio_play = new QMediaPlayer(this);
    connect(audio_play, &QMediaPlayer::mediaStatusChanged, this, &wxapi::deal_audio_play);

    timer.setInterval(2000);
    connect(&timer, &QTimer::timeout, this, &wxapi::onTimeout);
    count = 0;
    abort_sig = false;
}

wxapi::~wxapi()
{

}

void wxapi::doubao_networkRequestInterface(QString url, QByteArray body)
{
    QNetworkRequest request;

    QSslConfiguration config = QSslConfiguration::defaultConfiguration();
    config.setPeerVerifyMode(QSslSocket::VerifyNone);
    config.setProtocol(QSsl::AnyProtocol);
    request.setSslConfiguration(config);

    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
    QString token = "Bearer " + api_key;
    request.setRawHeader(QByteArray("Authorization"), token.toUtf8());

    request.setUrl(QUrl(url));
    QNetworkReply *reply = manager->post(request, body);
    connect(reply, SIGNAL(finished()), this, SLOT(doubao_finished()));
    connect(reply, SIGNAL(readyRead()), this, SLOT(readyReadInterface()));
}

void wxapi::baidu_networkRequestInterface(QString url, QByteArray body)
{
    QNetworkRequest request;
    QSslConfiguration config = QSslConfiguration::defaultConfiguration();
    config.setPeerVerifyMode(QSslSocket::VerifyNone);
    config.setProtocol(QSsl::AnyProtocol);
    request.setSslConfiguration(config);
    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
    //request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");

    request.setUrl(QUrl(url));
    QNetworkReply *reply = manager->post(request, body);
    connect(reply, &QNetworkReply::finished, this, &wxapi::baidu_finished);
    connect(reply, &QNetworkReply::readyRead, this, &wxapi::readyReadInterface);
}

void wxapi::init_audio_play()
{
    file.setFileName("E:/QtProject/AiAudioAssistant/audio.mp3");
    file.remove();
    audio_play->stop();
    audio_play->setMedia(QMediaContent());
    qDebug() << "file removed ..." << file.fileName() <<  __func__;
}

void wxapi::post_content_to_doubao(QString text)
{
    qDebug() << "post_content_to_doubao..." << __func__;
    QJsonObject mesObj;
    mesObj.insert("role", "user");
    mesObj.insert("content", text);
    QJsonArray  mesArr;
    mesArr.append(mesObj);
    QJsonObject mesAll;
    mesAll.insert("model", mode_id);
    mesAll.insert("messages", mesArr);
    QJsonDocument mesDoc;
    mesDoc.setObject(mesAll);
    QByteArray tmp = mesDoc.toJson();
    //qDebug() << "send content of json:" << tmp;
    doubao_networkRequestInterface(post_doubao_url, tmp);

}

void wxapi::post_pcmData_to_baidu(QByteArray pcmData)
{
    this->pcmData.clear();
    this->pcmData = pcmData;
    qDebug() << "Get pcmData from widget..." << __func__;
    QJsonObject mesObj;
    mesObj.insert("format", "pcm");
    mesObj.insert("rate", 16000);
    mesObj.insert("channel", 1);
    mesObj.insert("token", audio_access_token);
    mesObj.insert("cuid", "OrMEg8C0rId140cv7ThSZILuoToS6Q8C");
    mesObj.insert("speech", QString(pcmData.toBase64()));
    mesObj.insert("len", pcmData.size());
    QByteArray tmp = QJsonDocument(mesObj).toJson();
    baidu_networkRequestInterface(audio_rec_url, tmp);

}

void wxapi::post_text_to_baidu_mix1(QString text)
{
    qDebug() << "post_text_to_baidu_mix1..." << __func__;
    QJsonObject textBody;
    textBody.insert("text", text);
    textBody.insert("lang", "zh");
    textBody.insert("format", "mp3-16k");
    textBody.insert("voice", 111);

    QByteArray body = QJsonDocument(textBody).toJson();
    audioMix_createTask_url = QString(audioMix_createTask_url_module).arg(audio_access_token);
    baidu_networkRequestInterface(audioMix_createTask_url, body);
    timer.start();
}

void wxapi::post_text_to_baidu_mix2()
{
    //qDebug() << "post_text_to_baidu_mix2..." << __func__;
    qDebug() << "task_ids..." << task_id << __func__;
    QJsonArray task_ids_Arr;
    task_ids_Arr.append(task_id);
    QJsonObject textBody;
    textBody.insert("task_ids", task_ids_Arr);
    QByteArray body = QJsonDocument(textBody).toJson();
    audioMix_QueryTask_url = QString(audioMix_QueryTask_url_module).arg(audio_access_token);
    baidu_networkRequestInterface(audioMix_QueryTask_url, body);
}

void wxapi::download_audio_from_url(QString url)
{
    QString tmp = "E:/QtProject/AiAudioAssistant/audio.mp3";
    file.setFileName(tmp);
    if(file.open(QIODevice::ReadWrite) == false)
    {
        qDebug() << "open audio.mp3 error..." << __func__;
        return;
    }

    QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(url)));
    connect(reply, &QNetworkReply::finished, this, &wxapi::get_speech_data_finished);
    connect(reply, &QNetworkReply::readyRead, this, &wxapi::readyReadInterface);
}

void wxapi::deal_audio_play(QMediaPlayer::MediaStatus status)
{
    if (status == QMediaPlayer::EndOfMedia || status == QMediaPlayer::InvalidMedia) {
               // 延迟删除临时文件（确保播放器释放资源）
               QTimer::singleShot(500, [this]() {
                   if (file.exists()) {
                       file.remove();
                       qDebug() << "已删除临时文件:" << file.fileName();
                   }
               });
               audio_play->stop();
               audio_play->setMedia(QMediaContent());
           }
}

void wxapi::get_speech_data_finished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "下载失败:" << reply->errorString();
        file.remove();
        return;
    }
    file.flush();
    file.close();


    audio_play->setMedia(QUrl::fromLocalFile(file.fileName()));
    QTimer::singleShot(100, this, [=](){});
    audio_play->play();
    emit OnScreenDisSig(doubao_text);
    qDebug() << "get_speech_data_finished..." << __func__;
    reply->deleteLater();
}

void wxapi::onTimeout()
{
    emit mix_task_query_sig();
    count++;
    if(count > 30)
    {
        abort_sig = true;
        count = 0;
        timer.stop();
        timer.setInterval(2000);
    }
}

QString wxapi::get_access_token_interface(QByteArray data, QString key)
{
    QJsonParseError parseErr;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseErr);
    if(parseErr.error == QJsonParseError::NoError)
    {
        if(!jsonDoc.isNull() && jsonDoc.isObject())
        {
            QJsonObject jsonObj = jsonDoc.object();
            if(jsonObj.contains(key))
            {
                QJsonValue jsonVal = jsonObj.value(key);
                if(jsonVal.isString())
                {
                    return jsonVal.toString();
                }
            }
        }
    }else{
        qDebug()<< "parseError:" << parseErr.errorString() << __func__;
    }
    return nullptr;
}

QString wxapi::get_pcm_text_interface(QByteArray data, QString key)
{
    QJsonParseError parseErr;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseErr);
    if(parseErr.error == QJsonParseError::NoError)
    {
        if(!jsonDoc.isNull() && jsonDoc.isObject())
        {
            QJsonObject jsonObj = jsonDoc.object();
            if(jsonObj.contains(key))
            {
                QJsonValue jsonVal = jsonObj.value(key);
                if(jsonVal.isArray())
                {
                    QJsonArray jsonArr = jsonVal.toArray();
                    return jsonArr.first().toString();
                }
            }
        }
    }else{
        qDebug()<< "parseError:" << parseErr.errorString() << __func__;
    }
    return nullptr;
}

QString wxapi::get_query_reply_interface(QByteArray data, QString  key1, QString key2, QString key3)
{
    QJsonParseError parseErr;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseErr);
    if(parseErr.error == QJsonParseError::NoError)
    {
        if(!jsonDoc.isNull() && jsonDoc.isObject())
        {
            QJsonObject jsonObj = jsonDoc.object();
            if(jsonObj.contains(key1))
            {
                QJsonValue jsonVal = jsonObj.value(key1);
                if(jsonVal.isArray())
                {
                    QJsonArray jsonArr = jsonVal.toArray();
                    if(jsonArr.at(0).isObject())
                    {
                        QJsonObject jsonMes = jsonArr.at(0).toObject();
                        if(jsonMes.contains(key2))
                        {
                            QJsonValue jsonVal = jsonMes.value(key2);
                            if(jsonVal.isString())
                            {
                                if(jsonVal.toString() == "Success")
                                {
                                    timer.stop();
                                    timer.setInterval(2000);
                                    count = 0;
                                    return jsonMes.value(key3).toObject().value("speech_url").toString();
                                }
                            }
                        }
                    }
                }
            }
        }
    }else{
        qDebug()<< "parseError:" << parseErr.errorString() << __func__;
    }
    return nullptr;
}

QString wxapi::get_doubao_reply_interface(QByteArray data, QString key1, QString key2, QString key3)
{
    QJsonParseError parseErr;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseErr);
    if(parseErr.error == QJsonParseError::NoError)
    {
        if(!jsonDoc.isNull() && jsonDoc.isObject())
        {
            QJsonObject jsonObj = jsonDoc.object();
            if(jsonObj.contains(key1))
            {
                QJsonValue jsonVal = jsonObj.value(key1);
                if(jsonVal.isArray())
                {
                    QJsonArray jsonArr = jsonVal.toArray();
                    if(jsonArr.at(0).isObject())
                    {
                        QJsonObject jsonMes = jsonArr[0].toObject();
                        if(jsonMes.contains(key2))
                        {
                            QJsonValue jsonVal = jsonMes.value(key2);
                            if(jsonVal.isObject())
                            {
                                QJsonObject jsonCtx = jsonVal.toObject();
                                if(jsonCtx.contains(key3))
                                {
                                    jsonVal = jsonCtx.value(key3);
                                    if(jsonVal.isString())
                                    {
                                        // qDebug() << "content:" << jsonVal.toString() << __func__;
                                        return jsonVal.toString();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }else{
        qDebug()<< "parseError:" << parseErr.errorString() << __func__;
    }
    return nullptr;
}

void wxapi::readyReadInterface()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if(abort_sig == true)
    {
        reply->abort();
        qDebug() << "请求超时,终止请求..." << __func__;
        emit reply_abort_sig();
        abort_sig = false;
        reply->deleteLater();
    }
    if(reply->error() == QNetworkReply::NoError)
    {
        QByteArray data = reply->readAll();
        if(reply->url() == QUrl(get_audio_token_url))
        {
            //qDebug() << data;
            QString findKey = "access_token";
            audio_access_token = get_access_token_interface(data, findKey);
            qDebug() << "access_token:" << audio_access_token;
        }

        if(reply->url() == QUrl(audio_rec_url))
        {
            //qDebug() << data;
            QString findKey = "result";
            QString pcm_text = get_pcm_text_interface(data, findKey);
            emit send_text_to_doubao_sig(pcm_text);
            qDebug() << "pcm convert to text:" << pcm_text;
        }

        if(reply->url() == QUrl(post_doubao_url))
        {
            //qDebug() << data;
            QString findKey1 = "choices";
            QString findKey2 = "message";
            QString findKey3 = "content";
            doubao_text = get_doubao_reply_interface(data, findKey1, findKey2, findKey3);
            emit text_convert_audio_sig(doubao_text);
            qDebug() << "get doubao reply context:" << doubao_text;
        }

        if(reply->url() == QUrl(audioMix_createTask_url))
        {

            //qDebug() << data;
            QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
            if(jsonDoc.object().contains("error_msg"))
            {
                qDebug() << "audioMix_createTask failed..." << __func__;
            }else{
                task_id = jsonDoc.object().value("task_id").toString();
                emit mix_task_query_sig();
            }
        }

        if(reply->url() == QUrl(audioMix_QueryTask_url))
        {
            //qDebug() << data;
            QString findKey1 = "tasks_info";
            QString findKey2 = "task_status";
            QString findKey3 = "task_result";
            QString tmp_url = get_query_reply_interface(data, findKey1, findKey2, findKey3);
            if(!tmp_url.isNull())
            {
                qDebug() << "speech_url:" << tmp_url << __func__;
                audio_url = tmp_url;
                emit download_audio_sig(tmp_url);
                task_id.clear();
            }
        }

        if(reply->url() == QUrl(audio_url))
        {
            //qDebug() << data;
            if (file.write(data) == -1) {
                qDebug() << "写入错误:" << file.errorString();
            }
        }

    }else{
        qDebug() << "Request: error ..." << __func__;
    }
}

void wxapi::doubao_finished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    reply->deleteLater();
    qDebug() << "Request: doubao_finished..." << __func__;
}

void wxapi::baidu_finished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    reply->deleteLater();
    //qDebug() << "Request: baidu_finished..." << __func__;
}






